#include "gtest/gtest.h"
#include "Graphe.h"

using namespace tp2;

class GrapheTesteur: public ::testing::Test
{
public:
	Graphe<int> graphe;
};

TEST_F(GrapheTesteur, constructeursVideOK)
{
	EXPECT_EQ(0, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetOrdre)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetDebutGrand)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetDebutPetit)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(3, 30);

	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetAscend)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);
	graphe.ajouterSommet(6, 60);

	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetDejaNumero)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_THROW(graphe.ajouterSommet(3, 40), std::logic_error);
	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, ajouterSommetDejaEtiquette)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_THROW(graphe.ajouterSommet(3, 30), std::logic_error);
	EXPECT_EQ(3, graphe.nombreSommets());
}

TEST_F(GrapheTesteur, enleverSommet)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_EQ(3, graphe.nombreSommets());

	graphe.enleverSommet(2);

	EXPECT_EQ(2, graphe.nombreSommets());
	EXPECT_FALSE(graphe.sommetExiste(2));
}

TEST_F(GrapheTesteur, sommetExiste)
{
	graphe.ajouterSommet(1, 10);

	EXPECT_TRUE(graphe.sommetExiste(1));
}

TEST_F(GrapheTesteur, sommetNonExiste)
{
	graphe.ajouterSommet(1, 10);

	EXPECT_FALSE(graphe.sommetExiste(2));
}

TEST_F(GrapheTesteur, etiquetteExiste)
{
	graphe.ajouterSommet(1, 10);

	EXPECT_TRUE(graphe.etiquetteExiste(10));
}

TEST_F(GrapheTesteur, etiquetteNonExiste)
{
	graphe.ajouterSommet(1, 10);

	EXPECT_FALSE(graphe.etiquetteExiste(20));
}

TEST_F(GrapheTesteur, sommetExisteMultiple)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(1, 10);

	EXPECT_TRUE(graphe.sommetExiste(1));
	EXPECT_TRUE(graphe.sommetExiste(2));
	EXPECT_TRUE(graphe.sommetExiste(4));
}

TEST_F(GrapheTesteur, getEtiquette)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(1, 10);

	EXPECT_EQ(10, graphe.getEtiquetteSommet(1));
	EXPECT_EQ(20, graphe.getEtiquetteSommet(2));
	EXPECT_EQ(40, graphe.getEtiquetteSommet(4));
}

TEST_F(GrapheTesteur, getEtiquetteNotExist)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(1, 10);

	EXPECT_THROW(graphe.getEtiquetteSommet(3), std::logic_error);
	EXPECT_THROW(graphe.getEtiquetteSommet(5), std::logic_error);
}

TEST_F(GrapheTesteur, getNumero)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(1, 10);

	EXPECT_EQ(1, graphe.getNumeroSommet(10));
	EXPECT_EQ(4, graphe.getNumeroSommet(40));
	EXPECT_EQ(2, graphe.getNumeroSommet(20));
}

TEST_F(GrapheTesteur, getNumeroNotExist)
{
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(1, 10);

	EXPECT_THROW(graphe.getNumeroSommet(44), std::logic_error);
	EXPECT_THROW(graphe.getNumeroSommet(22), std::logic_error);
	EXPECT_THROW(graphe.getNumeroSommet(11), std::logic_error);
}

TEST_F(GrapheTesteur, listerSommets)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	std::vector<int> v = graphe.listerSommets();

	EXPECT_EQ(1, v[0]);
	EXPECT_EQ(2, v[1]);
	EXPECT_EQ(3, v[2]);
}

TEST_F(GrapheTesteur, listerEtiquettes)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	std::vector<int> v = graphe.listerEtiquetteSommets();

	EXPECT_EQ(10, v[0]);
	EXPECT_EQ(20, v[1]);
	EXPECT_EQ(30, v[2]);
}

TEST_F(GrapheTesteur, ajouterArc)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);

	EXPECT_TRUE(graphe.arcExiste(1, 2));
}

TEST_F(GrapheTesteur, ajouterArcExiste)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);

	EXPECT_TRUE(graphe.arcExiste(1, 2));
	EXPECT_THROW(graphe.ajouterArc(1, 2, 1), std::logic_error);
}

TEST_F(GrapheTesteur, ajouterArcLuiMeme)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 1, 0);

	EXPECT_TRUE(graphe.arcExiste(1, 1));
}

TEST_F(GrapheTesteur, ajouterArcPlusieurs)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);

	EXPECT_TRUE(graphe.arcExiste(1, 2));
	EXPECT_TRUE(graphe.arcExiste(1, 3));
	EXPECT_TRUE(graphe.arcExiste(2, 3));
	EXPECT_TRUE(graphe.arcExiste(3, 1));
}

TEST_F(GrapheTesteur, ajouterArcNoSommet)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	EXPECT_THROW(graphe.ajouterArc(1, 5, 1), std::logic_error);
	EXPECT_THROW(graphe.ajouterArc(4, 5, 1), std::logic_error);
	EXPECT_THROW(graphe.ajouterArc(4, 2, 1), std::logic_error);
}

TEST_F(GrapheTesteur, enleverArc)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);

	graphe.enleverArc(1, 2);

	EXPECT_FALSE(graphe.arcExiste(1, 2));
}

TEST_F(GrapheTesteur, enleverArcPlusieurs)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);

	graphe.enleverArc(1, 2);
	graphe.enleverArc(2, 3);

	EXPECT_FALSE(graphe.arcExiste(1, 2));
	EXPECT_TRUE(graphe.arcExiste(1, 3));
	EXPECT_FALSE(graphe.arcExiste(2, 3));
	EXPECT_TRUE(graphe.arcExiste(3, 1));
}

TEST_F(GrapheTesteur, OrdreSortie)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);

	EXPECT_EQ(2, graphe.ordreSortieSommet(1));
	EXPECT_EQ(1, graphe.ordreSortieSommet(2));
	EXPECT_EQ(1, graphe.ordreSortieSommet(3));
}

TEST_F(GrapheTesteur, OrdreEntree)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);

	EXPECT_EQ(1, graphe.ordreEntreeSommet(1));
	EXPECT_EQ(1, graphe.ordreEntreeSommet(2));
	EXPECT_EQ(2, graphe.ordreEntreeSommet(3));
}

TEST_F(GrapheTesteur, sommetAdjacent)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 1, 1);
	graphe.ajouterArc(3, 4, 1);
	graphe.ajouterArc(3, 5, 1);

	std::vector<int> v = graphe.listerSommetsAdjacents(1);
	EXPECT_EQ(2, v[0]);
	EXPECT_EQ(3, v[1]);
}

TEST_F(GrapheTesteur, dijsktra)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 3);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 5, 1);
	graphe.ajouterArc(1, 4, 3);
	graphe.ajouterArc(4, 5, 2);

	std::vector<int> v(4);
	v[0] = 10;
	v[1] = 20;
	v[2] = 30;
	v[3] = 50;

	std::vector<int> v2;

	EXPECT_THROW(graphe.dijkstra(5, 50, v2), std::logic_error);

	int cout = 0;
	cout = graphe.dijkstra(10, 50, v2);

	EXPECT_EQ(cout, 3);
	EXPECT_EQ(v2[0], 10);
	EXPECT_EQ(v2[1], 20);
	EXPECT_EQ(v2[2], 30);
	EXPECT_EQ(v2[3], 50);
}

TEST_F(GrapheTesteur, bellmanFord)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 3);
	graphe.ajouterArc(2, 3, 1);
	graphe.ajouterArc(3, 5, 1);
	graphe.ajouterArc(1, 4, 3);
	graphe.ajouterArc(4, 5, 2);

	std::vector<int> v (4);
	v[0] = 10;
	v[1] = 20;
	v[2] = 30;
	v[3] = 50;

	std::vector<int> v2;

	EXPECT_TRUE(true);

	//graphe.bellmanFord(10,50,v2);
/*
	EXPECT_EQ(v2[0],10);
	EXPECT_EQ(v2[1],20);
	EXPECT_EQ(v2[2],30);
	EXPECT_EQ(v2[3],50);*/
}

TEST_F(GrapheTesteur, copieGraphe)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);

	graphe.ajouterArc(1, 2, 1);
	graphe.ajouterArc(1, 3, 1);
	graphe.ajouterArc(2, 3, 1);

	Graphe<int>* graphe2 = new Graphe<int>(graphe);

	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	EXPECT_EQ(3, graphe2->nombreSommets());
}

TEST_F(GrapheTesteur, fermetureGraphe)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 3, 3);
	graphe.ajouterArc(3, 4, 4);
	graphe.ajouterArc(4, 5, 5);
	graphe.ajouterArc(5, 1, 6);

	Graphe<int> fermeture = graphe.fermetureGraphe();

	std::cout << fermeture;
}

TEST_F(GrapheTesteur, fermetureGraphe2)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 3, 3);
	graphe.ajouterArc(3, 4, 4);
	graphe.ajouterArc(4, 5, 5);

	Graphe<int> fermeture = graphe.fermetureGraphe();

	std::cout << fermeture;
}

TEST_F(GrapheTesteur, fortementConnexe)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 3, 3);
	graphe.ajouterArc(3, 4, 4);
	graphe.ajouterArc(4, 5, 5);
	graphe.ajouterArc(5, 1, 6);

	EXPECT_TRUE(graphe.estFortementConnexe());
}

TEST_F(GrapheTesteur, fortementConnexeNot)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 3, 3);
	graphe.ajouterArc(4, 5, 5);
	graphe.ajouterArc(5, 1, 6);
	graphe.getCoutArc(1, 2);

	EXPECT_FALSE(graphe.estFortementConnexe());
}

TEST_F(GrapheTesteur, composantesFortementConnexe)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 1, 3);

	graphe.ajouterArc(3, 4, 4);
	graphe.ajouterArc(4, 5, 5);
	graphe.ajouterArc(5, 3, 6);

	std::vector<std::vector<int> > v;
	graphe.getComposantesFortementConnexes(v);

	for (unsigned int i = 0; i < v.size(); i++)
	{
		for (unsigned int j = 0; j < v[i].size(); j++)
		{
			std::cout << v[i][j];
		}
		std::cout << std::endl;
	}
}

TEST_F(GrapheTesteur, composantesFortementConnexeNone)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	std::vector<std::vector<int> > v;
	graphe.getComposantesFortementConnexes(v);

	for (unsigned int i = 0; i < v.size(); i++)
	{
		for (unsigned int j = 0; j < v[i].size(); j++)
		{
			std::cout << v[i][j];
		}
		std::cout << std::endl;
	}
}

TEST_F(GrapheTesteur, pointsArticulation)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 0);
	graphe.ajouterArc(2, 1, 0);
	graphe.ajouterArc(2, 3, 0);
	graphe.ajouterArc(3, 2, 0);
	graphe.ajouterArc(3, 4, 0);
	graphe.ajouterArc(4, 3, 0);
	graphe.ajouterArc(4, 5, 0);
	graphe.ajouterArc(5, 4, 0);
	graphe.ajouterArc(5, 1, 0);
	graphe.ajouterArc(1, 5, 0);

	std::vector<int> adj;

	for(int i = 1; i <= 5; i++)
	{
		adj = graphe.listerSommetsAdjacents(i);
		for(unsigned j = 0; j < adj.size(); j++)
		{
			std::cout << adj[j];
		}
		std::cout << " - " << adj.size();
		std::cout << std::endl;
	}

	/*std::vector<int> v;
	graphe.getPointsArticulation(v);

	for (unsigned int i = 0; i < v.size(); i++)
	{
		std::cout << v[i];
	}*/
}

TEST_F(GrapheTesteur, pointsArticulation2)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 0);
	graphe.ajouterArc(2, 1, 0);

	graphe.ajouterArc(3, 4, 0);
	graphe.ajouterArc(4, 3, 0);

	graphe.ajouterArc(4, 5, 0);
	graphe.ajouterArc(5, 4, 0);
	graphe.ajouterArc(5, 1, 0);
	graphe.ajouterArc(1, 5, 0);

	std::vector<int> v;
	graphe.getPointsArticulation(v);

	for (unsigned int i = 0; i < v.size(); i++)
	{
		std::cout << v[i];
	}
}

TEST_F(GrapheTesteur, pointsArticulation3)
{
	graphe.ajouterSommet(1, 10);
	graphe.ajouterSommet(2, 20);
	graphe.ajouterSommet(3, 30);
	graphe.ajouterSommet(4, 40);
	graphe.ajouterSommet(5, 50);

	graphe.ajouterArc(1, 2, 2);
	graphe.ajouterArc(2, 1, 3);

	graphe.ajouterArc(3, 4, 4);
	graphe.ajouterArc(4, 5, 5);
	graphe.ajouterArc(5, 3, 6);

	std::vector<int> v;
	graphe.getPointsArticulation(v);

	for (unsigned int i = 0; i < v.size(); i++)
	{
		std::cout << v[i];
	}
}
